package com.qd.panda.service.hk;

import cn.hutool.core.math.Money;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cdqidi.constant.ConstantDto;
import com.cdqidi.db.BaseService;
import com.cdqidi.dto.CacheKey;
import com.cdqidi.excel.ExcelExport;
import com.cdqidi.excel.util.ExportPage;
import com.cdqidi.exception.ApiException;
import com.cdqidi.util.DateUtil;
import com.cdqidi.util.RedisTemplateUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.qd.common.panda.constant.PandaConstant;
import com.qd.common.panda.domain.entity.hk.HkParkOrderDTO;
import com.qd.common.panda.domain.entity.hk.HkParkOrderStatisticsDTO;
import com.qd.common.panda.domain.entity.hk.HkPushLogDTO;
import com.qd.panda.mapper.hk.HkParkOrderMapper;
import com.qd.panda.model.HkParkOrder;
import com.qd.panda.service.park.CarParkService;
import com.qd.panda.service.stroke.DisplayUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDate;
import java.util.*;

import static java.util.stream.Collectors.toList;

/**
 * 临停订单
 *
 * @author sjk
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class HkParkOrderService extends BaseService<HkParkOrderMapper, HkParkOrder> {

    private static final String PREFIX_ID = "panda_hk_park_order_orderLogId_{0}";

    private final RedisTemplateUtil<HkParkOrder> redisTemplateUtil;
    private final CarParkService carParkService;
    private final ObjectMapper objectMapper;
    @Resource
    private HttpServletResponse response;

    /**
     * 保存
     *
     * @param dto 页面对象
     * @return 页面对象
     */
    @Transactional(rollbackFor = Exception.class)
    public HkParkOrderDTO save(HkParkOrderDTO dto) {
        final HkParkOrder model = dtoToModel(dto);
        try {
            if (super.save(model)) {
                return modelToDto(model, false);
            }
            throw new ApiException("添加失败");
        } finally {
            clearCache(model);
            model.freeData();
        }
    }

    /**
     * 修改
     *
     * @param dto 页面对象
     * @return 页面对象
     */
    @Transactional(rollbackFor = Exception.class)
    public HkParkOrderDTO update(HkParkOrderDTO dto) {
        final HkParkOrder historyModel = Optional.ofNullable(getById(dto.getOrderLogId())).orElseThrow(() -> new ApiException("ID不存在,不能更新"));
        final HkParkOrder model = dtoToModel(dto);
        try {
            if (super.updateById(model)) {
                return modelToDto(model, false);
            }
            throw new ApiException("更新失败");
        } finally {
            clearCache(historyModel);
            historyModel.freeData();
            model.freeData();
        }
    }

    /**
     * 批量添加
     *
     * @param mList 数据库对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveBatch(List<HkParkOrder> mList) {
        try {
            if (!super.saveBatch(mList)) {
                throw new ApiException("批量添加失败");
            }
        } finally {
            clearCaches(mList);
        }
    }

    /**
     * 批量更新
     *
     * @param mList 数据库对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateBatchIds(List<HkParkOrder> mList) {
        final List<String> ids = mList.stream().map(HkParkOrder::getOrderLogId).collect(toList());
        final List<HkParkOrder> historyModelList = checkIds(ids);
        try {
            if (!super.updateBatchById(mList)) {
                throw new ApiException("批量更新失败");
            }
        } finally {
            clearCaches(historyModelList);
            historyModelList.clear();
            ids.clear();
        }
    }

    /**
     * 删除，单个
     *
     * @param orderLogId 主键
     */
    @Transactional(rollbackFor = Exception.class)
    public void removeById(String orderLogId) {
        final HkParkOrder historyModel = Optional.ofNullable(getById(orderLogId)).orElseThrow(() -> new ApiException("数据不存在,不能删除"));
        try {
            if (!super.removeById(orderLogId)) {
                throw new ApiException("删除失败");
            }
        } finally {
            clearCache(historyModel);
            historyModel.freeData();
        }
    }

    /**
     * 批量删除
     *
     * @param ids 主键集合
     */
    @Transactional(rollbackFor = Exception.class)
    public void removeBatchIds(List<String> ids) {
        final List<HkParkOrder> historyModelList = checkIds(ids);
        try {
            if (!super.removeByIds(ids)) {
                throw new ApiException("批量删除失败");
            }
        } finally {
            clearCaches(historyModelList);
            historyModelList.clear();
        }
    }

    /**
     * 根据传入对象构建查询参数，判断是否存在
     *
     * @param dto 参数
     * @return 存在为true
     */
    @Transactional(readOnly = true)
    public Boolean isExists(HkParkOrderDTO dto) {
        final QueryWrapper<HkParkOrder> queryWrapper = createQueryWrapper(dto);
        final boolean exists = super.count(queryWrapper) > 0;
        queryWrapper.clear();
        return exists;
    }

    /**
     * 根据主键判断数据是否存在
     *
     * @param orderLogId 主键
     * @return 存在为true
     */
    @Transactional(readOnly = true)
    public Boolean isExistsById(String orderLogId) {
        boolean exists = false;
        if (StringUtils.hasLength(orderLogId)) {
            final HkParkOrder model = getById(orderLogId);
            exists = (null != model);
            if (exists) {
                model.freeData();
            }
        }
        return exists;
    }

    /**
     * 根据主键获取数据
     *
     * @param orderLogId 主键
     * @return 单条记录
     */
    @Transactional(readOnly = true)
    public HkParkOrder getById(String orderLogId) {
        final String key = RedisTemplateUtil.getRedisCacheKey(PREFIX_ID, orderLogId);
        return redisTemplateUtil.get(new CacheKey().setKey(key).setTimeout(ConstantDto.REDIS_TIME_OUT_DAY), () -> super.getById(orderLogId), HkParkOrder.class);
    }

    /**
     * 根据主键获取数据
     *
     * @param orderLogId 主键
     * @return 单条记录，转换成页面对象
     */
    @Transactional(readOnly = true)
    public HkParkOrderDTO getByIdDto(String orderLogId) {
        return Optional.ofNullable(getById(orderLogId)).map(model -> modelToDto(model, true)).orElse(null);
    }

    /**
     * 根据条件查询单条数据
     *
     * @param dto 查询参数
     * @return 单条记录
     */
    @Transactional(readOnly = true)
    public HkParkOrder getOne(HkParkOrderDTO dto) {
        final QueryWrapper<HkParkOrder> queryWrapper = createQueryWrapper(dto);
        HkParkOrder model = super.getOne(queryWrapper);
        queryWrapper.clear();
        return model;
    }

    /**
     * 根据条件查询单条数据
     *
     * @param dto 查询参数
     * @return 单条记录，转换成页面对象
     */
    @Transactional(readOnly = true)
    public HkParkOrderDTO getOneDto(HkParkOrderDTO dto) {
        return Optional.ofNullable(getOne(dto)).map(model -> modelToDto(model, true)).orElse(null);
    }

    /**
     * 根据条件查询列表数据
     *
     * @param dto 查询参数
     * @return 列表数据
     */
    @Transactional(readOnly = true)
    public List<HkParkOrder> getList(HkParkOrderDTO dto) {
        final QueryWrapper<HkParkOrder> queryWrapper = createQueryWrapper(dto);
        final List<HkParkOrder> list = super.list(queryWrapper);
        queryWrapper.clear();
        return list;
    }

    /**
     * 根据条件查询列表数据
     *
     * @param dto 查询参数
     * @return 列表数据，转换成页面对象
     */
    @Transactional(readOnly = true)
    public List<HkParkOrderDTO> getListDto(HkParkOrderDTO dto) {
        return modelToDtoList(getList(dto));
    }

    /**
     * 分页数据
     *
     * @param page 分页对象
     * @param dto  查询参数
     * @return 分页信息
     */
    @Transactional(readOnly = true)
    public IPage<HkParkOrderDTO> page(Page<HkParkOrder> page, HkParkOrderDTO dto) {
        final QueryWrapper<HkParkOrder> queryWrapper = createQueryWrapper(dto);
        return baseMapper.page(page, queryWrapper);
    }

    /**
     * 分页数据
     *
     * @param page 分页对象
     * @param dto  查询参数
     * @return 分页信息
     */
    @Transactional(readOnly = true)
    public IPage<HkParkOrderDTO> invoicablePage(Page<HkParkOrder> page, HkParkOrderDTO dto) {
        LocalDate end = LocalDate.now();
        LocalDate start = end.plusDays(-60);
        final QueryWrapper<HkParkOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("t1.pay_status",DisplayUtil.PAY_STATUS_1);
        queryWrapper.eq("t1.user_id",dto.getUserId());
        queryWrapper.isNull("t2.order_id");
        queryWrapper.between("t1.pay_time",DateUtil.localDateToStr(start)+" 00:00:00",DateUtil.localDateToStr(end)+" 23:59:59");
        queryWrapper.orderByAsc("t1.pay_time");
        return baseMapper.invoicablePage(page, queryWrapper);
    }

    /**
     * 清空缓存
     *
     * @param model 数据库对象
     */
    public void clearCache(HkParkOrder model) {
        if (null == model) {
            return;
        }
        redisTemplateUtil.deleteByKey(RedisTemplateUtil.getRedisCacheKey(PREFIX_ID, model.getOrderLogId()));
    }

    /**
     * 批量清空缓存
     *
     * @param list 数据库对象
     */
    public void clearCaches(List<HkParkOrder> list) {
        if (null == list || list.isEmpty()) {
            return;
        }
        List<String> ids = list.stream().map(model -> RedisTemplateUtil.getRedisCacheKey(PREFIX_ID, model.getOrderLogId())).collect(toList());
        if (!ids.isEmpty()) {
            redisTemplateUtil.deleteByKey(ids);
            ids.clear();
        }
    }

    /**
     * 数据库对象转页面对象
     *
     * @param model 数据库对象
     * @return 页面对象
     */
    public HkParkOrderDTO modelToDto(HkParkOrder model, boolean isPush) {
        if (null == model) {
            return null;
        }
        final HkParkOrderDTO dto = new HkParkOrderDTO();
        dto.setOrderLogId(model.getOrderLogId());
        dto.setInUnid(model.getInUnid());
        dto.setBillCode(model.getBillCode());
        dto.setVehicleColor(model.getVehicleColor());
        dto.setPlateColor(model.getPlateColor());
        dto.setEnterTime(model.getEnterTime());
        dto.setCostTime(model.getCostTime());
        dto.setParkPeriodTime(model.getParkPeriodTime());
        dto.setTotalCost(model.getTotalCost());
        dto.setDeductMoney(model.getDeductMoney());
        dto.setPayMoney(model.getPayMoney());
        dto.setArrearsTime(model.getArrearsTime());
        dto.setBerthCode(model.getBerthCode());
        dto.setAddTime(model.getAddTime());
        dto.setPayStatus(model.getPayStatus());
        dto.setPayTime(model.getPayTime());
        dto.setPhone(model.getPhone());
        dto.setBid(model.getBid());
        dto.setOrderType(model.getOrderType());
        dto.setParkId(model.getParkId());
        dto.setPlateNumber(model.getPlateNumber());
        dto.setUserId(model.getUserId());
        dto.setPayMethod(model.getPayMethod());
        dto.setWalletAmount(model.getWalletAmount());
        dto.setWalletGiveAmount(model.getWalletGiveAmount());
        dto.setParkName(model.getParkName());
        buildDisplay(dto, isPush);
        return dto;
    }

    /**
     * 页面对象转数据库对象
     *
     * @param dto 页面对象
     * @return 数据库对象
     */
    public HkParkOrder dtoToModel(HkParkOrderDTO dto) {
        if (null == dto) {
            return null;
        }
        final HkParkOrder model = new HkParkOrder();
        model.setOrderLogId(dto.getOrderLogId());
        model.setInUnid(dto.getInUnid());
        model.setBillCode(dto.getBillCode());
        model.setVehicleColor(dto.getVehicleColor());
        model.setPlateColor(dto.getPlateColor());
        model.setEnterTime(dto.getEnterTime());
        model.setCostTime(dto.getCostTime());
        model.setParkPeriodTime(dto.getParkPeriodTime());
        model.setTotalCost(dto.getTotalCost());
        model.setDeductMoney(dto.getDeductMoney());
        model.setPayMoney(dto.getPayMoney());
        model.setArrearsTime(dto.getArrearsTime());
        model.setBerthCode(dto.getBerthCode());
        model.setAddTime(dto.getAddTime());
        model.setPayTime(dto.getPayTime());
        model.setPayStatus(dto.getPayStatus());
        model.setPhone(dto.getPhone());
        model.setBid(dto.getBid());
        model.setOrderType(dto.getOrderType());
        model.setParkId(dto.getParkId());
        model.setPlateNumber(dto.getPlateNumber());
        model.setUserId(dto.getUserId());
        model.setPayMethod(dto.getPayMethod());
        model.setWalletAmount(dto.getWalletAmount());
        model.setWalletGiveAmount(dto.getWalletGiveAmount());
        model.setParkName(dto.getParkName());
        return model;
    }

    /**
     * 码表转换
     *
     * @param dto 页面对象
     */
    public void buildDisplay(HkParkOrderDTO dto, boolean isPush) {
        if (!StringUtils.hasLength(dto.getParkName())) {
            dto.setParkName(carParkService.idToDisplay(dto.getParkId()));
        }
        if (!StringUtils.hasLength(dto.getOrderTypeDisplay())) {
            if (dto.getOrderType().equals(PandaConstant.HK_ORDER_TYPE_1)) {
                dto.setOrderTypeDisplay("临停");
            }
            if (dto.getOrderType().equals(PandaConstant.HK_ORDER_TYPE_1)) {
                dto.setOrderTypeDisplay("欠费");
            }
        }
        if (!StringUtils.hasLength(dto.getPayMoneyDisplay()) && null != dto.getPayMethod()) {
            if (dto.getPayMethod() == PandaConstant.PAY_METHOD_WX) {
                dto.setPayMethodDisplay("微信支付");
            }
            if (dto.getPayMethod() == PandaConstant.PAY_METHOD_WALLET) {
                dto.setPayMethodDisplay("钱包支付");
            }
        }
        if (null != dto.getArrearsTime()) {
            dto.setArrearsTimeDisplay(DateUtil.longToLocalDateTime(dto.getArrearsTime()));
        }
        if (null != dto.getCostTime()) {
            dto.setCostTimeDisplay(DateUtil.longToLocalDateTime(dto.getCostTime()));
        }
        if (null != dto.getEnterTime()) {
            dto.setEnterTimeDisplay(DateUtil.longToLocalDateTime(dto.getEnterTime()));
        }
        if (null != dto.getPayStatus()) {
            dto.setPayStatusDisplay(DisplayUtil.getPayStatusDisplay(dto.getPayStatus()));
        }
        if (isPush) {
            if (StringUtils.hasLength(dto.getBillCode()) && StringUtils.hasLength(dto.getInUnid())) {
                if (null != dto.getPayStatus()) {
                    if (dto.getPayStatus().equals(DisplayUtil.PAY_STATUS_1)) {
                        Integer sendState = sendState(dto.getInUnid(), dto.getBillCode());
                        dto.setPushState(Objects.requireNonNullElse(sendState, -1));
                    } else {
                        dto.setPushState(-1);
                    }
                    if (dto.getPushState().equals(-1)) {
                        dto.setPushStateDisplay("未推送");
                    } else if (dto.getPushState().equals(0)) {
                        dto.setPushStateDisplay("推送成功");
                    } else if (dto.getPushState().equals(1)) {
                        dto.setPushStateDisplay("推送失败");
                    } else {
                        dto.setPushStateDisplay("未知状态");
                    }
                }
            }
        }
    }

    /**
     * 数据库对象转页面对象
     *
     * @param list 数据库对象
     * @return 页面对象
     */
    public List<HkParkOrderDTO> modelToDtoList(List<HkParkOrder> list) {
        return Optional.ofNullable(list).orElse(Collections.emptyList()).stream().map(model -> modelToDto(model, true)).collect(toList());
    }

    /**
     * 页面对象转数据库对象
     *
     * @param list 页面对象
     * @return 数据库对象
     */
    public List<HkParkOrder> dtoToModelList(List<HkParkOrderDTO> list) {
        return Optional.ofNullable(list).orElse(Collections.emptyList()).stream().map(this::dtoToModel).collect(toList());
    }

    public QueryWrapper<HkParkOrder> createQueryWrapper(HkParkOrderDTO dto) {
        return createQueryWrapper(dto, "", true);
    }

    /**
     * 拼装查询参数，除了主键的其他字段会自动加入进来
     *
     * @param dto 查询参数，不为空的属性会被自动加入
     */
    public QueryWrapper<HkParkOrder> createQueryWrapper(HkParkOrderDTO dto, String tableAlias, boolean isOrderBy) {
        final QueryWrapper<HkParkOrder> queryWrapper = new QueryWrapper<>();
        if (null != dto) {
            if (StringUtils.hasLength(tableAlias) && tableAlias.charAt(tableAlias.length() - 1) != '.') {
                tableAlias += ".";
            }
            if (StringUtils.hasLength(dto.getOrderLogId())) {
                Object[] orderLogIds = dto.getOrderLogId().split(",");
                queryWrapper.in(tableAlias + "order_log_id", orderLogIds);
            }
            if (StringUtils.hasLength(dto.getInUnid())) {
                queryWrapper.eq(tableAlias + "in_unid", dto.getInUnid());
            }
            if (StringUtils.hasLength(dto.getBillCode())) {
                queryWrapper.eq(tableAlias + "bill_code", dto.getBillCode());
            }
            if (StringUtils.hasLength(dto.getPhone())) {
                queryWrapper.like(tableAlias + "phone", dto.getPhone());
            }
            if (StringUtils.hasLength(dto.getParkId())) {
                queryWrapper.eq(tableAlias + "park_id", dto.getParkId());
            }
            if (StringUtils.hasLength(dto.getParkName())) {
                queryWrapper.like(tableAlias + "park_name", dto.getParkName());
            }
            if (StringUtils.hasLength(dto.getPlateNumber())) {
                queryWrapper.like(tableAlias + "plate_number", dto.getPlateNumber());
            }
            if (null != dto.getPayStatus()) {
                queryWrapper.eq(tableAlias + "pay_status", dto.getPayStatus());
            }
            if (null != dto.getOrderType()) {
                queryWrapper.eq(tableAlias + "order_type", dto.getOrderType());
            }
            if (StringUtils.hasLength(dto.getBeginTime()) && !StringUtils.hasLength(dto.getEndTime())) {
                queryWrapper.between(tableAlias + "pay_time", dto.getBeginTime() + " 00:00:00", dto.getBeginTime() + " 23:59:59");
            }
            if (!StringUtils.hasLength(dto.getBeginTime()) && StringUtils.hasLength(dto.getEndTime())) {
                queryWrapper.between(tableAlias + "pay_time", dto.getEndTime() + " 00:00:00", dto.getEndTime() + " 23:59:59");
            }
            if (StringUtils.hasLength(dto.getBeginTime()) && StringUtils.hasLength(dto.getEndTime())) {
                queryWrapper.between(tableAlias + "pay_time", dto.getBeginTime() + " 00:00:00", dto.getEndTime() + " 23:59:59");
            }
            if (null != dto.getPayMethod()) {
                queryWrapper.eq(tableAlias + "pay_method", dto.getPayMethod());
            }
        }
        if (isOrderBy) {
            queryWrapper.orderByDesc(tableAlias + "pay_time");
            queryWrapper.orderByAsc(tableAlias + "bid");
        }
        return queryWrapper;
    }

    /**
     * 批量检查主键在数据库中是否存在
     *
     * @param ids 主键集合
     * @return 主键查询出来的集合
     */
    public List<HkParkOrder> checkIds(List<String> ids) {
        if (null == ids || ids.isEmpty()) {
            throw new ApiException("ids不能为空");
        }
        final List<HkParkOrder> list = super.listByIds(ids);
        if (list.isEmpty()) {
            throw new ApiException("ids不存在" + Arrays.toString(ids.toArray()));
        }
        if (ids.size() == list.size()) {
            return list;
        }
        List<String> dbIds = list.stream().map(HkParkOrder::getOrderLogId).collect(toList());
        final List<String> notExistsList = ids.stream().filter(id -> !dbIds.contains(id)).collect(toList());
        dbIds.clear();
        if (!notExistsList.isEmpty()) {
            throw new ApiException("ids不存在" + Arrays.toString(notExistsList.toArray()));
        }
        return list;
    }

    @Transactional(readOnly = true)
    public List<HkParkOrder> getListByBid(String bid) {
        final QueryWrapper<HkParkOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("bid", bid);
        List<HkParkOrder> hkParkOrders = getBaseMapper().selectList(queryWrapper);
        queryWrapper.clear();
        return hkParkOrders;
    }

    @Transactional(readOnly = true)
    public boolean paySuccess(String billCode) {
        final QueryWrapper<HkParkOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("bill_code", billCode);
        queryWrapper.eq("pay_status", DisplayUtil.PAY_STATUS_1);
        boolean exists = baseMapper.exists(queryWrapper);
        queryWrapper.clear();
        return exists;
    }

    @Transactional(readOnly = true)
    public HkParkOrder getOneByBid(String bid) {
        final QueryWrapper<HkParkOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("sum(pay_money) as pay_money,add_time,pay_status,plate_number,park_id,park_period_time,order_type");
        queryWrapper.eq("bid", bid);
        queryWrapper.last("limit 1");
        HkParkOrder hkParkOrder = baseMapper.selectOne(queryWrapper, false);
        queryWrapper.clear();
        return hkParkOrder;
    }

    /**
     * 查询推送状态
     *
     * @param inUnid   海康唯一标识
     * @param billCode 海康订单号
     * @return -1未推送 0推送成功 1推送失败
     */
    public Integer sendState(@Param("inUnid") String inUnid, @Param("billCode") String billCode) {
        List<HkPushLogDTO> stateList = baseMapper.state(inUnid, billCode);
        if (null == stateList || stateList.isEmpty()) {
            return -1;
        }
        for (HkPushLogDTO hkPushLogDTO : stateList) {
            if (hkPushLogDTO.getSendState() == 0 && count() > 0) {
                return 0;
            }
        }
        return 1;
    }

    /**
     * 导出Excel
     *
     * @param query 查询条件
     */
    @Transactional(readOnly = true)
    public void export(HkParkOrderDTO query) {
        final ExportPage<HkParkOrder, HkParkOrderDTO> exportPage = new ExportPage<>();
        try {
            final List<HkParkOrderDTO> list = exportPage.getAllForPage(page -> page(page, query).getRecords());
            try {
                ExcelExport.downloadExcel(response, HkParkOrderDTO.class, () -> list);
            } catch (IOException e) {
                log.error("导出失败", e);
                throw new ApiException("导出失败");
            }
        } finally {
            exportPage.freeData();
        }
    }

    @Transactional(readOnly = true)
    public ArrayNode statisticsHkOrder(HkParkOrderDTO query) {
        QueryWrapper<HkParkOrder> queryWrapper = createQueryWrapper(query, "", false);
        queryWrapper.groupBy("pay_method");
        final List<HkParkOrderStatisticsDTO> list = baseMapper.sumMoney(queryWrapper);
        Money totalCost = new Money();
        Money deductMoney = new Money();
        Money payMoney = new Money();
        long quantity = 0;
        for (HkParkOrderStatisticsDTO hkParkOrderStatisticsDTO : list) {
            totalCost = totalCost.add(new Money(hkParkOrderStatisticsDTO.getTotalCostDisplay()));
            deductMoney = deductMoney.add(new Money(hkParkOrderStatisticsDTO.getDeductMoneyDisplay()));
            payMoney = payMoney.add(new Money(hkParkOrderStatisticsDTO.getPayMoneyDisplay()));
            quantity = quantity + hkParkOrderStatisticsDTO.getQuantity();
        }
        ArrayNode arrayNode = objectMapper.createArrayNode();
        ObjectNode objectNode = createNode(totalCost, deductMoney, payMoney, quantity, 3);

        arrayNode.add(objectNode);
        if (list.isEmpty()) {
            objectNode = createNode(1);
            arrayNode.add(objectNode);
            objectNode = createNode(2);
            arrayNode.add(objectNode);
        } else {
            HkParkOrderStatisticsDTO one = list.stream().filter(hkParkOrderStatisticsDTO -> hkParkOrderStatisticsDTO.getPayMethod() == 1).findFirst().orElse(null);
            HkParkOrderStatisticsDTO two = list.stream().filter(hkParkOrderStatisticsDTO -> hkParkOrderStatisticsDTO.getPayMethod() == 2).findFirst().orElse(null);
            if (null == one) {
                objectNode = createNode(1);
                arrayNode.add(objectNode);
            } else {
                objectNode = createNode(new Money(one.getTotalCostDisplay()), new Money(one.getDeductMoneyDisplay()), new Money(one.getPayMoneyDisplay())
                        , one.getQuantity(), 1);
                arrayNode.add(objectNode);
                one.freeData();
            }
            if (null == two) {
                objectNode = createNode(2);
                arrayNode.add(objectNode);
            } else {
                objectNode = createNode(new Money(two.getTotalCostDisplay()), new Money(two.getDeductMoneyDisplay()), new Money(two.getPayMoneyDisplay())
                        , two.getQuantity(), 2);
                arrayNode.add(objectNode);
                two.freeData();
            }
            list.clear();
        }
        return arrayNode;
    }

    private ObjectNode createNode(Money totalCost, Money deductMoney, Money payMoney, long quantity, int payMethod) {
        ObjectNode objectNode = objectMapper.createObjectNode();
        objectNode.put("totalCost", totalCost.getAmount().toString());
        objectNode.put("deductMoney", deductMoney.getAmount().toString());
        objectNode.put("payMoney", payMoney.getAmount().toString());
        objectNode.put("quantity", quantity);
        objectNode.put("pay_method", payMethod);
        return objectNode;
    }

    private ObjectNode createNode(int payMethod) {
        ObjectNode objectNode = objectMapper.createObjectNode();
        objectNode.put("totalCost", "0.00");
        objectNode.put("deductMoney", "0.00");
        objectNode.put("payMoney", "0.00");
        objectNode.put("quantity", 0);
        objectNode.put("pay_method", payMethod);
        return objectNode;
    }

    @Transactional(readOnly = true)
    public List<HkParkOrder> getListByUserIdAndOrderLogIds(String userId, List<String> orderIds) {
        final QueryWrapper<HkParkOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("user_id", userId);
        queryWrapper.in("pay_status", DisplayUtil.PAY_STATUS_1);
        queryWrapper.in("order_log_id", orderIds);
        List<HkParkOrder> list = getBaseMapper().selectList(queryWrapper);
        queryWrapper.clear();
        return list;
    }
}